#include<iostream>
#include<string>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>


#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

using namespace std;

#define Retry_Count 5

bool VisitServer(const string& serverip, uint16_t serverport,int* cnt)
{
     //1.创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in serveraddr;
    memset(&serveraddr,0,sizeof(serveraddr));
    serveraddr.sin_family=AF_INET;
    serveraddr.sin_port=htons(serverport);
    inet_pton(AF_INET,serverip.c_str(),&serveraddr.sin_addr);//将字符串转换为网络字节序
    //serveraddr.sin_addr.s_addr=inet_addr(serverip.c_str());//将字符串转换为网络字节序

    bool ret=true;

    if(sockfd<0)
    {
        cerr<<"socket error"<<endl;
        return false;
    }

    //2.要不要绑定呢？client必须要有IP和Port，需要绑定的，但是不需要用户显示的bind，系统会自动分配一个端口
    //发起连接的时候，client会被Os自动本地绑定的

    //2.建立连接

    int n=connect(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr));//自己进行bind
    if(n<0)
    {
        cerr<<"connect error"<<endl;
        ret=false;
        goto END;
    }

    *cnt=0;//重连成功后，重置重试次数
    while(true)
    {
        string inbuffer;
        cout<<"please Enter#    ";
        getline(cin,inbuffer);
        if(inbuffer=="quit")break;//如果用户输入quit，则退出循环
        size_t n=write(sockfd,inbuffer.c_str(),inbuffer.size());
        if(n>0)
        {
            char buffer[1024];
            size_t m=read(sockfd,buffer,sizeof(buffer)-1);
            if(m>0)
            {
                buffer[m]=0;
                cout<<"get a echo message "<<buffer<<endl;
            }
            else if(m==0)//服务器关闭
            {
                break;
            }
            else
            {
                ret=false;
                goto END;
            }
        }
        else
        {
            ret=false;
            goto END;
        }
    }
END:
    close(sockfd);
    return ret;
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        cout << "Usage:\n     ./udp_echo_client <ip> <port>" << endl;
        return -1;
    }

    string serverip=argv[1];
    uint16_t serverport=atoi(argv[2]);

    int cnt=1;
    while(cnt<=Retry_Count)
    {
        bool result=VisitServer(serverip,serverport,&cnt);
        if(result)
        {
            break;
        }
        else
        {
            sleep(1);
            cout<<"server offonline,retrying..."<<cnt<<endl;
            cnt++;
        }
    }
   if(cnt>=Retry_Count)
   {
        cout<<"server offonline,exiting..."<<endl;
   }
    return 0;
}